/** biome-ignore-all lint/suspicious/noExplicitAny: off */
import { ContextWithMiddleware } from './ContextWithMiddleware';
import type { TypedKey } from './types';

declare global {
  interface Window {
    __REDUX_DEVTOOLS_EXTENSION__?: {
      connect: (options?: {
        name?: string;
        actionSanitizer?: (action: any) => any;
        stateSanitizer?: (state: any) => any;
        trace?: boolean;
        traceLimit?: number;
      }) => {
        init: (state: any) => void;
        send: (action: any, state: any) => void;
        subscribe: (callback: (message: any) => void) => () => void;
        unsubscribe: () => void;
      };
    };
    __CONTEXT_DEVTOOLS__?: {
      getState: () => Record<string, unknown>;
      subscribe: (listener: () => void) => () => void;
      dispatch: (action: { type: string; payload?: unknown }) => void;
    };
  }
}

export class DevToolsContext extends ContextWithMiddleware {
  private devToolsListeners: Array<() => void> = [];
  private reduxDevTools: {
    init: (state: any) => void;
    send: (action: any, state: any) => void;
    subscribe: (callback: (message: any) => void) => () => void;
    unsubscribe: () => void;
  } | null = null;

  constructor() {
    super();
    this.setupDevTools();
    this.setupReduxDevTools();
  }

  private setupDevTools(): void {
    if (
      typeof window !== 'undefined' &&
      process.env.NODE_ENV === 'development'
    ) {
      window.__CONTEXT_DEVTOOLS__ = {
        getState: () => ({ ...this.data }),
        subscribe: (listener) => {
          this.devToolsListeners.push(listener);
          return () => {
            this.devToolsListeners = this.devToolsListeners.filter(
              (l) => l !== listener,
            );
          };
        },
        dispatch: (action) => {
          console.log('DevTools Action:', action);
        },
      };
    }
  }

  private setupReduxDevTools(): void {
    if (
      typeof window !== 'undefined' &&
      process.env.NODE_ENV === 'development' &&
      window.__REDUX_DEVTOOLS_EXTENSION__
    ) {
      try {
        // 连接Redux DevTools
        this.reduxDevTools = window.__REDUX_DEVTOOLS_EXTENSION__.connect({
          name: 'Typed Context',
          trace: true,
          traceLimit: 20,
        });

        // 初始化状态
        if (this.reduxDevTools) {
          this.reduxDevTools.init({ ...this.data });

          // 订阅Redux DevTools的操作
          this.reduxDevTools.subscribe((message) => {
            if (message.type === 'DISPATCH' && message.state) {
              // 处理时间旅行和状态重置
              const newState = JSON.parse(message.state);
              this.data = { ...newState };
              this.notifyListeners('*', this.data);
            }
          });
        }
      } catch (error) {
        console.error('Failed to connect to Redux DevTools:', error);
        this.reduxDevTools = null;
      }
    }
  }

  setData<T>(key: TypedKey<T>, value: T, immediate = true): void {
    const oldValue = this.getData(key);
    super.setData(key, value, immediate);

    // 发送更新到Redux DevTools
    if (this.reduxDevTools) {
      const action = {
        type: `SET_${key.key.toUpperCase()}`,
        payload: { key: key.key, value, oldValue },
      };
      this.reduxDevTools.send(action, { ...this.data });
    }
  }

  protected notifyListeners(key: string, newValue: unknown): void {
    super.notifyListeners(key, newValue);
    this.notifyDevTools();
  }

  private notifyDevTools(): void {
    this.devToolsListeners.forEach((listener) => {
      try {
        listener();
      } catch (error) {
        console.error('DevTools listener error:', error);
      }
    });
  }
}
